<?php
// composer下载方式
// 先使用composer命令下载：
// composer require owner888/phpspider
// 引入加载器
//require './vendor/autoload.php';

// GitHub下载方式

require_once "common.php";
require __DIR__ . '/../vendor/autoload.php';

use phpspider\core\phpspider;
use phpspider\core\log;
use phpspider\core\selector;

/* Do NOT delete this comment */
/* 不要删除这段注释 */

$configs = array(
    'name' => '保温网',
    'log_show' => true,
    'log_file' => 'data/test_baowenwang.log',
    'log_type' => 'error,warn,debug',
    'input_encoding' => null,  //input_encoding默认值为null，即程序自动识别页面编码
    'output_encoding' => 'utf-8', //output_encoding默认值为utf-8, 如果数据库为gbk编码，请修改为gb2312
    'tasknum' => 1,      //tasknum默认值为1，即单进程任务爬取     进程数
    'timeout' => 5,     //爬虫爬取每个网页的超时时间 单位秒
    'max_try' => 2 ,    // 爬虫爬取每个网页失败后尝试次数 重复爬取2次
    'max_depth' => 3,   //爬虫爬取网页深度，超过深度的页面不再采集
    'max_fields' => 1, //爬虫爬取内容网页最大条数 抓取到一定的字段后退出  默认值为0，即不限制
    'user_agent' => phpspider::AGENT_PC,  //爬虫爬取网页所使用的浏览器类型
    'client_ip' => [                  //爬虫爬取网页所使用的伪IP，用于破解防采集
        '192.168.0.2',
        '192.168.0.3',
        '192.168.0.4',
    ],
    'export' => [         //爬虫爬取数据导出
        'type' => 'db',      //type：导出类型 csv、sql、db
        'table' => 'spider',   // 如果数据表没有数据新增请检查表结构和字段名是否匹配
    ],

    'db_config' => [      //数据库配置
        'host' => '127.0.0.1',
        'port' => '3306',
        'user' => 'root',
        'pass' => 'root',     //密码
        'name' => 'php_spider'  //数据库名
    ],
    'domains' => [        //定义爬虫爬取哪些域名下的网页, 非域名下的url会被忽略以提高爬取速度
        'www.cnbaowen.net',
    ],
    'scan_urls' =>[    //定义爬虫的入口链接, 爬虫从这些链接开始爬取,同时这些链接也是监控爬虫所要监控的链接
        'http://www.cnbaowen.net/news/list-3717.html'         //入口
    ],
    'content_url_regexes' => [   //定义内容页url的规则
        'http://www.cnbaowen.net/news/show-\d+.html'         //文章详情
    ],
    'list_url_regexes' => [   //定义列表页url的规则  对于有列表页的网站, 使用此配置可以大幅提高爬虫的爬取速率
        'http://www.cnbaowen.net/news/list-3717-\d+.html'     //分页
    ],

    'fields' => [       //定义内容页的抽取规则  规则由一个个field组成, 一个field代表一个数据抽取项
        [
            'name' => "title",   //要跟数据库表中的字段一致
            'selector' => "//div[@class='exTitle']",  //定义抽取规则, 默认使用xpath
            'selector_type'=>'xpath',  //目前可用xpath, jsonpath, regex   默认目前可用xpath
            'required' => true,   // 定义该field的值是否必须, 默认false  赋值为true的话, 如果该field没有抽取到内容, 该field对应的整条数据都将被丢弃
            'repeated' => false,  //定义该field抽取到的内容是否是有多项, 默认false  赋值为true的话, 无论该field是否真的是有多项, 抽取到的结果都是数组结构
            'children'=>null,  //为此field定义子项 子项的定义仍然是一个fields数组  没错, 这是一个树形结构
        ],
        [
            'name' => 'read_num',   //阅读量
            'selector' => "//div[@class='exTiInfo']",
            'required' => true,
        ],
        [
            'name' => 'content',   //文章内容
            'selector' => "//div[@id='article']",
            'required' => true,
        ],
        [
            'name' => 'site_url'
        ],
        [
            'name' => 'site_id'
        ],
    ],
);


p($configs);die;

$spider = new phpspider($configs);

dump($spider);die;

//开始回调
$spider->on_start = function ($spider) {
    echo "on_start回调开始 ".PHP_EOL;
    for ($i = 1; $i <= 1; $i++) {
        $url = "http://www.cnbaowen.net/news/list-3717-{$i}.html";
        echo "on_start:".$url.PHP_EOL;
        $spider->add_url($url);
    }
    echo "on_start回调结束 ".PHP_EOL;
};

//判断
/**
 * @param $status_code  当前网页的请求返回的HTTP状态码
 * @param $url  当前网页URL
 * @param $content  当前网页内容
 * @param $phpspider  爬虫对象
 * @return bool  $content 返回处理后的网页内容，不处理当前页面请返回false
 */
$spider->on_status_code = function($status_code, $url, $content, $phpspider)
{
    // 如果状态码为429，说明对方网站设置了不让同一个客户端同时请求太多次
    if ($status_code == '429')
    {
        // 将url插入待爬的队列中,等待再次爬取
        $phpspider->add_url($url);
        // 当前页先不处理了
        return false;
    }
    // 不拦截的状态码这里记得要返回，否则后面内容就都空了
    return $content;
};

//判断是否设置了反爬虫
/**
 * @param $url 当前网页的url
 * @param $content 当前网页内容
 * @param $phpspider 爬虫对象
 * @return bool
 */
$spider->is_anti_spider = function($url, $content, $phpspider)
{
    // 当前页面没有被反爬虫，可以继续处理
    return false;
};

/** 在一个网页下载完成之后调用. 主要用来对下载的网页进行处理.
 * @param $page  当前下载的网页页面的对象
 * @param $page['url'] 当前网页的URL
 * @param $page['raw'] 当前网页的内容
 * @param $page['request'] 当前网页的请求对象
 * @param $phpspider   爬虫对象
 * @return mixed  返回处理后的网页内容
 */
$spider->on_download_page = function($page, $phpspider)
{
    return $page;
};

/** 在一个网页下载完成之后调用. 主要用来对下载的网页进行处理.
 * @param $content  当前下载的网页内容
 * @param $phpspider  爬虫对象
 * @return mixed  返回处理后的网页内容
 */
$spider->on_download_attached_page = function($content, $phpspider)
{
    return $content;
};

/** 在一个网页获取到URL之后调用. 主要用来对获取到的URL进行处理.
 * @param $url  当前获取到的URL
 * @param $phpspider  爬虫对象
 * @return bool  返回处理后的URL，为false则此URL不入采集队列
 */
$spider->on_fetch_url = function($url, $phpspider)
{

    return $url;
};

/**
 * @param $page  当前下载的网页页面的对象
 * @param $page['url'] 当前网页的URL
 * @param $page['raw'] 当前网页的内容
 * @param $page['request'] 当前网页的请求对象
 * @param $content  当前网页内容
 * @param $phpspider  当前爬虫对象
 * @return bool  返回false表示不需要再从此网页中发现待爬url
 */
$spider->on_scan_page = function($page, $content, $phpspider)
{
    return false;
};

//列表回调
/**
 * @param $page
 * @param $content
 * @param $spider
 * @return bool
 */
$spider->on_list_page = function ($page, $content, $spider) {    //$page = ["url"=>"","raw"=>"","request"=[]]
    echo "on_list_page回调开始 ".PHP_EOL;
//    p("url:".$page['url']);
    p($page);
    $page_type = gettype($page);
    p("page:".$page_type);

    if($page_type == 'array'){
        foreach ($page as $k=>$val){
            $val_type = gettype($val);
            p("$k:".$val_type);
            if($val_type == 'array'){
                foreach ($page[$k] as $k1=>$val1){
                    $val1_type = gettype($val1);
                    p("$k1:".$val1_type);
                }
            }
        }
    }
    $content_type = gettype($content);
    p("content:".$content_type);
    p($content);

    $content = selector::select($content, "//div[@class='news-list-box']");// 右侧详情页
    if (is_array($content)) {
        $content = implode('', $content);
    }
    $regex = "#http://www.cnbaowen.net/news/show-\d+.html#";
    $urls = array();
    preg_match_all($regex, $content, $out);
    $urls = empty($out[0]) ? [] : $out[0];
    $urls = array_unique($urls);

    p($urls);

    if (!empty($urls)) {
        foreach ($urls as $url) {
            $spider->add_url($url);
        }
    }
    echo "on_list_page回调结束 ".PHP_EOL;
    // 通知爬虫不再从当前网页中发现待爬url
    return false;
};

/**
 * @param $page
 * @param $content
 * @param $phpspider
 * @return bool
 */
$spider->on_content_page = function ($page, $content, $phpspider) {
    echo "on_content_page回调开始 ".PHP_EOL;
    p($page['url']);
    p($content);
    p($page);

    echo "on_content_page回调结束 ".PHP_EOL;
    return false;
};

/** 在抽取到field内容之后调用, 对其中包含的img标签进行回调处理
 * @param $fieldname  当前field的name. 注意: 子field的name会带着父field的name, 通过.连接.
 * @param $img  整个img标签的内容
 * @return string|string[]
 */
$spider->on_handle_img = function($fieldname, $img)
{
    return $img;
};

/**  当一个field的内容被抽取到后进行的回调, 在此回调中可以对网页中抽取的内容作进一步处理
 * @param $fieldname  当前field的name. 注意: 子field的name会带着父field的name, 通过.连接.
 * @param $data  当前field抽取到的数据. 如果该field是repeated, data为数组类型, 否则是String
 * @param $page  当前下载的网页页面的对象
 * @return int|mixed|string
 */
$spider->on_extract_field = function ($fieldname, $data, $page) {
    echo "on_extract_field回调开始 ".PHP_EOL;
    p("fieldname：".$fieldname);
    p("data：".$data);
    p("filename_type:".gettype($fieldname));
    p("data_type:".gettype($data));
    p("page_type:".gettype($page));
    switch ($fieldname) {
        case 'title':
            $data = strip_tags($data);
            return $data;
        case 'read_num':
            $data = strip_tags($data);
            return $data;
        case 'content':
        {
            $s = preg_replace("/<div style=\"float:right[\s\S]*?div>/", "", $data);
            $s = preg_replace('/<a .*?href="(.*?)".*?>/is', "<a href='#'>", $s);
            $data = preg_replace('/<img.*?>/is', "", $s);
            $data = mb_substr($data, 0, 1000);
            echo "on_extract_field回调结束 ".PHP_EOL;
            $data = strip_tags($data);
            return $data;
        }
        case 'site_url':
            echo "on_extract_field回调结束 ".PHP_EOL;
            return $page['url'];
        case 'site_id':
            echo "on_extract_field回调结束 ".PHP_EOL;
            return 22;
        default:
            echo "on_extract_field回调结束 ".PHP_EOL;
            return $data;
    }
};

/** 在一个网页的所有field抽取完成之后, 可能需要对field进一步处理, 以发布到自己的网站
 * @param $page  当前下载的网页页面的对象
 * @param $data  当前网页抽取出来的所有field的数据
 * @return mixed  返回处理后的数据, 注意数据类型需要跟传进来的$data类型匹配
 */
$spider->on_extract_page = function($page, $data)
{
    return $data;
    // 返回false不处理，当前页面的字段不入数据库直接过滤
    // 比如采集电影网站，标题匹配到“预告片”这三个字就过滤
    //if (strpos($data['title'], "预告片") !== false)
    //{
    //    return false;
    //}
};

$spider->start();